﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.Threading;
using System.Net.Sockets;

public class RemotePlayer : MonoBehaviour {
	private Thread loop;
	private Queue<float[]> commandPosition = new Queue<float[]>();
	private Socket Remote;

	private Server server;

	public const short COMMAND_POSITION = 1;
	public const short COMMAND_ATTACK = 2;
	public const short COMMAND_DISCONNECT = 3;

	public const short PACKET_SIZE_POSITION = 10;

	void Start() {
		server = GameObject.Find("ServerHandler").GetComponent<Server>();
	}

	void OnDestroy() {
		Dispose ();
	}

	void Update() {
		while(commandPosition.Count > 0) {
			var poss = commandPosition.Dequeue();
			transform.position = new Vector2(poss[0], poss[1]);
			
			var bytes = new byte[8];
			BitConverter.GetBytes(poss[0]).CopyTo(bytes,0);
			BitConverter.GetBytes(poss[1]).CopyTo(bytes,4);
			server.PlayerPositionUpdated(Remote, bytes);
		}
	}

	public void StartRemoteControl(Socket s) {
		Debug.Log ("Remote Control Started");
		Remote = s;
		loop = new Thread(RemoteControl);
		loop.Start();
	}

	private void RemoteControl() {
		while(loop.IsAlive) {
			var commandNumber = Remote.ReadShort();

			switch (commandNumber) {
			case COMMAND_POSITION: 
				// Enqueue it to break it out of the thread and make it possible to change the position of things
				CreatePositionCommand(Remote.ReadFloat(), Remote.ReadFloat ());
				break;
			case COMMAND_ATTACK:
				Attack();
				break;
			case COMMAND_DISCONNECT:
				Disconnect();
				break;
			default:
				Debug.Log("Something was of : " + commandNumber);
				Dispose ();
				break;
			}
		}
	}

	public void CreatePositionCommand(float x, float y) {
		commandPosition.Enqueue(new float[] {x, y});
	}
	private void Attack() {
		// Read ids
		var victim = Remote.ReadShort();
		var killer = Remote.ReadShort();

		// Spread on connections
		server.PlayerDead(Remote, victim, killer);
	}
	public void Die() {
		DisplayDeath();
		StartCoroutine(RespawnIn());
	}
	private IEnumerator RespawnIn() {
		yield return new WaitForSeconds(3);
		CreatePositionCommand(0, 0);
	}
	public void DisplayDeath() {
		Debug.Log ("I know show I'm dead!");
		StartCoroutine(HideAndShow ());
	}
	private IEnumerator HideAndShow() {
		var x = gameObject.GetComponentInChildren<SpriteRenderer>().gameObject;
		x.SetActive(false);
		yield return new WaitForSeconds(3);
		x.SetActive(true);
	}
	private void Disconnect() {}

	public void Dispose() {
		if(loop != null && loop.IsAlive) loop.Abort();
		if(Remote != null) Remote.Close();
	}
}
